import sim.engine.*;
import ec.util.*;
import sim.util.*;
import sim.field.grid.*;

/* 
 * 	Epstein model converted from NetLogo in to MASON. 
 *  Initiate model and add agents to the grid. 
 *  
 *  This version reduces the govt legitimacy by a given amount on an given interval starting at a given time.
 */

public class Rebellion extends SimState{
	private static final long serialVersionUID = 1L;
	
	public int neighborhood = 1;

	public int gridHeight = 100;
	public int gridWidth = 100;
	
	public SparseGrid2D grid = new SparseGrid2D(gridWidth, gridHeight);
	public int copCount = 0;
	public int quietCount = 0;
	public int activeCount = 0;
	public int jailCount = 0;
	
	public int vision = 7;
	public double govtLegitimacy = 0.82;
	public double reductionAmount = 0;
	public int reductionInterval = 1;
	public int reductionStartDay = 0;
	
	public double copProbability = 0.04;
	public double civilianProbability = 0.7;
	
	public int maxJailTerm = 30;
	public double threshold = 0.1;
	
	public Rebellion(long seed) {
		super(new MersenneTwisterFast(seed), new Schedule());
	}

	public void start(){
		quietCount = 0;
		activeCount = 0;
		jailCount = 0;
		
		super.start(); //clear out the schedule
		
		grid = new SparseGrid2D(gridWidth, gridHeight);
		
		//add agents to grid and schedule
		for(int x = 0; x < gridWidth; x++){
			for(int y = 0; y < gridHeight; y++){
				double riskAversion = random.nextDouble();
				double perceivedHardship = random.nextDouble();
		
				Steppable agent = null;
				double d = random.nextDouble();
				if(d < copProbability){
					agent = new Cop(new Int2D(x, y), riskAversion, perceivedHardship);
					copCount++;
					schedule.scheduleRepeating(agent);
				}
				else if(d < copProbability + civilianProbability){
					agent = new Civilian(new Int2D(x, y), riskAversion, perceivedHardship);
					quietCount++;
					schedule.scheduleRepeating(agent);
				}
				grid.setObjectLocation(agent, x, y);
			}
		}
		
		//this schedule will reduce the jail term for all jailed agents after all agents have made their step
		Steppable jailTermReducer = new JailTermReducer();
		schedule.scheduleRepeating(jailTermReducer);
		
		Steppable legitimacyReducer = new LegitimacyReducer();
		schedule.scheduleRepeating(reductionStartDay, legitimacyReducer, reductionInterval);
	}
	
	public static void main(String[] args){
		doLoop(Rebellion.class, args);
		System.exit(0);
	}
	
	public int getVision() {return vision;}
	public void setVision(int vision) {this.vision = vision;}
	public double getGovtLegitimacy() {return govtLegitimacy;}
	public void setGovtLegitimacy(double govtLegitimacy) {this.govtLegitimacy = govtLegitimacy;}
	public double getReductionAmount() {return reductionAmount;}
	public void setReductionAmount(double reductionAmount) {this.reductionAmount = reductionAmount;}
	public int getReductionInterval() {return reductionInterval;}
	public void setReductionInterval(int reductionInterval) {this.reductionInterval = reductionInterval;}
	public int getReductionStartDay() {return reductionStartDay;}
	public void setReductionStartDay(int reductionDay) {this.reductionStartDay = reductionDay;}
	public double getCopProbability() {return copProbability;}
	public void setCopProbability(double copProbability) {this.copProbability = copProbability;}
	public double getCivilianProbability() {return civilianProbability;}
	public void setCivilianProbability(double civilianProbability) {this.civilianProbability = civilianProbability;}
	public int getMaxJailTerm() {return maxJailTerm;}
	public void setMaxJailTerm(int maxJailTerm) {this.maxJailTerm = maxJailTerm;}
	public double getThreshold() {return threshold;}
	public void setThreshold(double threshold) {this.threshold = threshold;}
	public int getActiveCount() {return activeCount;}
	public void setActiveCount(int activeCount) {this.activeCount = activeCount;}
	public int getQuietCount() {return quietCount;}
	public void setQuietCount(int quietCount) {this.quietCount = quietCount;}
	public int getJailCount() {return jailCount;}
	public void setJailCount(int jailCount) {this.jailCount = jailCount;}
}
